package com.dys.teststreamapi11;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @className: com.dys.teststreamapi11.StreamAPITest
 * @description: stream并行流处理线程安全的问题
 * @author: pine cone
 * @version: v1.0.0
 * @createTime: 2024/09/01 下午4:39
 */
public class StreamAPITest16 {
    /**
     * 这是一个main()方法,是应用程序的入口
     *
     * @param args 方法的形参列表,是一个字符串数组,包含了从命令行传递给程序的参数
     */
    public static void main(String[] args) {
        streamToThreadSafetyToArrayAndCollect();
    }

    /**
     * 在多线程的处理下，会出现线程安全问题
     * 针对这个问题，我们的解决方案有哪些呢？
     * 1.加同步锁
     * 2.使用线程安全的容器
     * 3.通过Stream中的toArray/collect操作
     */
    private static void streamToThreadSafety() {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            list.add(i);
        }
        System.out.println(list.size());
        System.out.println("----------------");
        List<Integer> listNew = new ArrayList<>();
        list.parallelStream()
                // .forEach(s -> listNew.add(s));
                .forEach(listNew::add);
        System.out.println(listNew.size());
    }

    /**
     * 1.加同步监视器
     */
    private static void streamToThreadSafetySync() {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            list.add(i);
        }
        System.out.println(list.size());
        System.out.println("----------------");
        List<Integer> listNew = new ArrayList<>();
        String str = "线程安全";
        list.parallelStream()
                .forEach(s -> {
                    synchronized (str) {
                        listNew.add(s);
                    }
                });
        System.out.println(listNew.size());
    }

    /**
     * 2.使用线程安全的容器
     */
    private static void streamToThreadSafetyContainer() {
        Vector v = new Vector();
        IntStream.rangeClosed(1, 1000)
                .parallel()
                .forEach(i -> {
                    v.add(i);
                });
        System.out.println(v.size());
    }

    /**
     * 3.将线程不安全的容器转为线程安全的容器
     */
    private static void streamToThreadSafetyContainer2() {
        List<Integer> list = new ArrayList<>();
        // 将线程不安全的容器转为线程安全的容器
        List<Integer> synchronizedList = Collections.synchronizedList(list);
        IntStream.rangeClosed(1, 10000).parallel()
                .forEach(i -> {
                    synchronizedList.add(i);
                });
        System.out.println(synchronizedList.size());
    }

    /**
     * 使用线程安全的容器
     */
    private static void streamToThreadSafetyContainer3() {
        CopyOnWriteArrayList<Integer> v = new CopyOnWriteArrayList();
        IntStream.rangeClosed(1, 1000)
                .parallel()
                .forEach(i -> {
                    v.add(i);
                });
        System.out.println(v.size());
    }

    /**
     * 通过Stream中的 toArray方法或者 collect方法来操作,就是满足线程安全的要求
     */
    private static void streamToThreadSafetyToArrayAndCollect() {
        List<Integer> listNew = IntStream.rangeClosed(1, 10000).parallel()
                .boxed()
                .collect(Collectors.toList());
        System.out.println(listNew.size());
    }

}
